#include "../include/flag.hpp"

#ifdef __CANYON_FLAG_enableLogging

#ifndef __CANYON_LOGGING
#define __CANYON_LOGGING

#include <concepts>
#include <iosfwd>

namespace canyon::logging{

template<typename T>
concept is_string = std::is_same_v<std::string, std::decay_t<T>> || std::is_same_v<const char *, std::decay_t<T>>;

enum log_level{
    DEBUG,
    INFO,
    WARN,
    ERROR,
    FATAL,
    NONE
};

struct log_metainfo{
    std::string name;
    void *addr;
};

struct log_signal_level{
    log_level level;
    log_signal_level(log_level level) : level(level){}
};

template<is_string T>
void log(log_level level, log_metainfo metainfo, T str, std::ostream & stream);

extern template void log<const char *>(log_level level, log_metainfo metainfo, const char *str, std::ostream & stream);
extern template void log<std::string>(log_level level, log_metainfo metainfo, std::string str, std::ostream & stream);

class logstream{
    public:
    log_level level;
    log_metainfo metainfo;

    logstream(log_metainfo metainfo = {.name = "", .addr = nullptr}, log_level level = log_level::INFO){
        this->metainfo = metainfo;
        this->level = level;
    }

    public:

    template<is_string T>
    logstream & operator<<(T str);

    logstream & operator<<(log_signal_level signal);
};

extern template logstream & logstream::operator<<<const char *>(const char *str);
extern template logstream & logstream::operator<<<std::string>(std::string str);

}

#endif
#endif
